package org.jeecg.modules.friends.service.impl;

import static java.util.stream.Collectors.toMap;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.collections4.ListUtils;
import org.apache.commons.compress.utils.Lists;
import org.jeecg.modules.friends.base.HttpReturn;
import org.jeecg.modules.friends.base.PageRsp;
import org.jeecg.modules.friends.base.PageUtil;
import org.jeecg.modules.friends.dao.MomentsLikeRecordsDAO;
import org.jeecg.modules.friends.model.MomentsLikeRecordsDO;
import org.jeecg.modules.friends.service.NewMomentsService;
import org.jeecg.modules.friends.service.req.MomentsReq;
import org.jeecg.modules.friends.service.req.PublishMomentsReviewReq;
import org.jeecg.modules.friends.service.req.SelectedPageListReq;
import org.jeecg.modules.friends.service.req.SetHiddenReq;
import org.jeecg.modules.friends.service.req.SetSelectedReq;
import org.jeecg.modules.friends.service.rsp.MomentReviewRsp;
import org.jeecg.modules.friends.service.rsp.MomentsInfoRsp;
import org.jeecg.modules.friends.service.rsp.MomentsRsp;
import org.jeecg.modules.friends.service.rsp.UnReadCountRsp;
import org.jeecg.modules.friends.service.rsp.UnReadMomentsReviewRsp;
import org.jeecg.modules.friends.store.entity.MomentsEntity;
import org.jeecg.modules.friends.store.entity.MomentsPicsEntity;
import org.jeecg.modules.friends.store.entity.MomentsReviewEntity;
import org.jeecg.modules.friends.store.mapper.MomentsMapper;
import org.jeecg.modules.friends.store.mapper.MomentsPicsMapper;
import org.jeecg.modules.friends.store.mapper.MomentsReviewMapper;
import org.jeecg.modules.friends.store.wrapper.MomentsPicsQuery;
import org.jeecg.modules.friends.store.wrapper.MomentsQuery;
import org.jeecg.modules.friends.store.wrapper.MomentsReviewQuery;
import org.jeecg.modules.friends.store.wrapper.MomentsReviewUpdate;
import org.jeecg.modules.friends.store.wrapper.MomentsUpdate;
import org.jeecg.modules.friends.user.entity.User;
import org.jeecg.modules.friends.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.org.atool.fluent.mybatis.model.StdPagedList;

/**
 * Created on 2025-01-21
 */
@Service
public class NewMomentsServiceImpl implements NewMomentsService {
    @Autowired
    private IUserService userService;
    @Autowired
    private MomentsMapper momentsMapper;
    @Autowired
    private MomentsReviewMapper momentsReviewMapper;
    @Autowired
    private MomentsPicsMapper momentsPicsMapper;
    @Autowired
    private MomentsLikeRecordsDAO momentsLikeRecordsDAO;

    @Override
    public HttpReturn<PageRsp<MomentsInfoRsp>> selectedPageList(SelectedPageListReq req, User user) {

        MomentsQuery limit;
        if (req.getMomentsId() != null) {
            limit = new MomentsQuery()
                    .where
                    .id().eq(req.getMomentsId(), Objects::nonNull)
                    .end()
                    .limit(req.limitStartPage(), req.limitEndPage())
                    .orderBy.id().desc().end();

            markReaded(req.getMomentsId(), user);
        } else {
            limit = new MomentsQuery()
                    .where
                    .hiddenFlag().isFalse()
                    .id().eq(req.getMomentsId(), Objects::nonNull)
                    .end()
                    .limit(req.limitStartPage(), req.limitEndPage())
                    .orderBy.id().desc().end();
        }

        if (req.getOrderSortType() != null) {
            if (req.getOrderSortType() == 1) {
                limit = new MomentsQuery()
                        .where
                        .hiddenFlag().isFalse()
                        .id().eq(req.getMomentsId(), Objects::nonNull)
                        .end()
                        .limit(req.limitStartPage(), req.limitEndPage()).orderBy.updateTime().asc().end();
            }
            if (req.getOrderSortType() == 2) {
                limit = new MomentsQuery()
                        .where
                        .hiddenFlag().isFalse()
                        .id().eq(req.getMomentsId(), Objects::nonNull)
                        .end()
                        .limit(req.limitStartPage(), req.limitEndPage()).orderBy.updateTime().desc().end();
            }
            if (req.getOrderSortType() == 3) {
                limit = new MomentsQuery()
                        .where
                        .hiddenFlag().isFalse()
                        .id().eq(req.getMomentsId(), Objects::nonNull)
                        .end()
                        .limit(req.limitStartPage(), req.limitEndPage()).orderBy.likeCount().asc().end();
            }
            if (req.getOrderSortType() == 4) {
                limit = new MomentsQuery()
                        .where
                        .hiddenFlag().isFalse()
                        .id().eq(req.getMomentsId(), Objects::nonNull)
                        .end()
                        .limit(req.limitStartPage(), req.limitEndPage()).orderBy.likeCount().desc().end();
            }
        }


        StdPagedList<MomentsEntity> momentsEntityStdPagedList = momentsMapper.stdPagedEntity(limit);
        List<MomentsEntity> data = momentsEntityStdPagedList.getData();
        if (CollectionUtil.isEmpty(data)) {
            return HttpReturn.successPageResult();
        }
        List<Long> momentsIdList = ListUtils.emptyIfNull(data).stream()
                .map(MomentsEntity::getId).collect(Collectors.toList());

        Set<Long> publishUserIds = ListUtils.emptyIfNull(data).stream()
                .map(MomentsEntity::getUserId).collect(Collectors.toSet());

        List<MomentsLikeRecordsDO> momentsLikeRecordsDOS = user == null ? Lists.newArrayList() :
                                                           momentsLikeRecordsDAO
                                                                   .queryByMomentsIdAndUserId(momentsIdList,
                                                                           user.getId());

        List<Long> momentsLikeIds = ListUtils.emptyIfNull(momentsLikeRecordsDOS).stream()
                .filter((x) -> x.getStatus() == 0)
                .map(MomentsLikeRecordsDO::getMomentsId).collect(Collectors.toList());

        List<MomentsReviewEntity> momentsReviewEntities = momentsReviewMapper.listEntity(
                new MomentsReviewQuery()
                        .where
                        .momentsId().in(momentsIdList)
                        .end()
                        .orderBy
                        .id().desc().end()
        );

        Set<Long> userIds = ListUtils.emptyIfNull(momentsReviewEntities).stream()

                .map(MomentsReviewEntity::getUserId).collect(Collectors.toSet());
        if (user != null) {
            userIds.add(user.getId());
        }
        userIds.addAll(publishUserIds);

        List<User> users = userService.listByIds(userIds);

        Map<Long, User> userMap = ListUtils.emptyIfNull(users).stream()
                .collect(toMap(User::getId, Function.identity(), (oldValue, newValue) -> newValue));


        Map<Long, List<MomentsReviewEntity>> momentsReviewEntityMap =
                ListUtils.emptyIfNull(momentsReviewEntities).stream()
                        .collect(Collectors.groupingBy(MomentsReviewEntity::getMomentsId));


        List<MomentsPicsEntity> momentsPicsEntities = momentsPicsMapper.listEntity(
                new MomentsPicsQuery()
                        .where
                        .momentsId().in(momentsIdList)
                        .end()
        );
        Map<Long, List<MomentsPicsEntity>> momentsPicsMap = ListUtils.emptyIfNull(momentsPicsEntities).stream()
                .collect(Collectors.groupingBy(MomentsPicsEntity::getMomentsId, Collectors.toList()));


        return PageUtil.transferPageHttpReturn(req, momentsEntityStdPagedList,
                (x) -> getMomentsInfoRsp(userMap, momentsReviewEntityMap, momentsPicsMap, x,
                        req.getMomentsId() != null, momentsLikeIds));
    }

    private void markReaded(Long momentsId, User user) {
        if (user == null) {
            return;
        }
        momentsReviewMapper.updateBy(
                new MomentsReviewUpdate()
                        .set.isRead().is(true)
                        .end()
                        .where
                        .momentsId().eq(momentsId)
                        .publishUserId().eq(user.getId())
                        .end()
        );
        momentsReviewMapper.updateBy(
                new MomentsReviewUpdate()
                        .set.atIsRead().is(true)
                        .end()
                        .where
                        .momentsId().eq(momentsId)
                        .atUserId().eq(user.getId())
                        .end()
        );


    }

    @Override
    public void publishMomentsReview(PublishMomentsReviewReq req, User user) {
        MomentsEntity momentsEntity = momentsMapper.findById(req.getMomentsId());
        if (momentsEntity == null) {
            return;
        }
        // 新增
        MomentsReviewEntity newMomentReviewEntity = new MomentsReviewEntity();
        newMomentReviewEntity.setMomentsId(req.getMomentsId());
        newMomentReviewEntity.setUserId(user.getId());
        newMomentReviewEntity.setUserNickName(user.getNickname());
        newMomentReviewEntity.setContent(req.getReviewContent());
        newMomentReviewEntity.setPublishUserId(momentsEntity.getUserId());
        if (req.getAtUserId() != null && req.getAtUserId() > 0) {
            User atUser = userService.findById(req.getAtUserId());
            if (atUser != null) {
                newMomentReviewEntity.setAtUserId(atUser.getId());
                newMomentReviewEntity.setAtUserNickName(atUser.getNickname());
                req.setAtUserName(atUser.getNickname());
            }
        }
        // 自己就标记未已读
        if (user.getId().equals(req.getAtUserId()) || user.getId().equals(momentsEntity.getUserId())) {
            newMomentReviewEntity.setAtIsRead(true);
            newMomentReviewEntity.setAtIsRead(true);
        } else {
            newMomentReviewEntity.setAtIsRead(false);
            newMomentReviewEntity.setIsRead(false);
        }

        momentsReviewMapper.insert(newMomentReviewEntity);
    }

    @Override
    public void setSelected(SetSelectedReq req) {
        MomentsEntity momentsEntity = momentsMapper.findById(req.getMomentsId());
        if (momentsEntity == null) {
            return;
        }
        // 设置精选
        momentsMapper.updateBy(
                new MomentsUpdate()
                        .set
                        .selected().is(req.isSelected()).end()
                        .where
                        .id().eq(req.getMomentsId())
                        .end()
        );

    }

    @Override
    public void setHidden(SetHiddenReq req) {
        MomentsEntity momentsEntity = momentsMapper.findById(req.getMomentsId());
        if (momentsEntity == null) {
            return;
        }
        // 设置精选
        momentsMapper.updateBy(
                new MomentsUpdate()
                        .set
                        .hiddenFlag().is(req.isHidden()).end()
                        .where
                        .id().eq(req.getMomentsId())
                        .end()
        );

    }

    private MomentsInfoRsp getMomentsInfoRsp(Map<Long, User> userMap,
            Map<Long, List<MomentsReviewEntity>> momentsReviewEntityMap,
            Map<Long, List<MomentsPicsEntity>> momentsPicsMap, MomentsEntity x, boolean showAllReview,
            List<Long> momentsLikeIds) {
        MomentsInfoRsp momentsInfoRsp = new MomentsInfoRsp();
        User publishUser = userMap.get(x.getUserId());
        if (publishUser != null) {
            momentsInfoRsp.setHeadPicUrl(publishUser.getHeadPicUrl());
            momentsInfoRsp.setNickName(StrUtil.blankToDefault(publishUser.getNickname(), publishUser.getName()));
            momentsInfoRsp.setGender(publishUser.getGender());
            momentsInfoRsp.setAge(publishUser.getBirthday());
            momentsInfoRsp.setCurrentResidence(publishUser.getCurrentResidence());
        }
        momentsInfoRsp.setUserId(x.getUserId());
        List<MomentsPicsEntity> momentsPicsEntities1 = momentsPicsMap.get(x.getId());
        if (CollectionUtil.isNotEmpty(momentsPicsEntities1)) {
            momentsInfoRsp.setPics(ListUtils.emptyIfNull(momentsPicsEntities1).stream()
                    .map(MomentsPicsEntity::getPicUrl).collect(Collectors.toList()));
        }
        momentsInfoRsp.setIsLike(momentsLikeIds.contains(x.getId()));
        momentsInfoRsp.setContent(x.getContent());
        momentsInfoRsp.setMomentsId(x.getId());
        momentsInfoRsp.setLikeCount(x.getLikeCount());
        momentsInfoRsp.setTime(DateUtil.format(x.getAddTime(), "yyyy-MM-dd HH:mm:ss"));
        List<MomentsReviewEntity> momentsReviewEntities1 = momentsReviewEntityMap.get(x.getId());
        if (CollectionUtil.isNotEmpty(momentsReviewEntities1)) {
            momentsReviewEntities1 = momentsReviewEntities1.stream().filter((c) -> {
                User user = userMap.get(c.getUserId());
                return user != null;
            }).collect(Collectors.toList());

            momentsInfoRsp.setReviewCount(momentsReviewEntities1.size());
            // 不展示所有评论
            if (!showAllReview) {

                momentsReviewEntities1 = momentsReviewEntities1.subList(0, Math.min(momentsReviewEntities1.size(), 2));
            }

            momentsInfoRsp.setReviewRsps(ListUtils.emptyIfNull(momentsReviewEntities1).stream()
                    .map((element) -> {
                        MomentReviewRsp momentReviewRsp = new MomentReviewRsp();
                        momentReviewRsp.setReviewContent("");


                        momentReviewRsp.setReviewContent(element.getContent());
                        momentReviewRsp.setUserId(element.getUserId());
                        User user = userMap.get(element.getUserId());

                        if (user != null) {
                            momentReviewRsp.setHeadPicUrl(user.getHeadPicUrl());
                            momentReviewRsp.setGender(user.getGender());
                            momentReviewRsp.setAge(user.getBirthday());
                            momentReviewRsp.setCurrentResidence(user.getCurrentResidence());
                            momentReviewRsp.setNickName(element.getUserNickName());
                        }
                        momentReviewRsp.setAtUserId(element.getAtUserId());
                        momentReviewRsp.setAtUserNickName(element.getAtUserNickName());
                        return momentReviewRsp;
                    }).collect(Collectors.toList()));


        }

        return momentsInfoRsp;
    }

    @Override
    public HttpReturn<PageRsp<MomentsRsp>> momentsPageList(MomentsReq req) {
        StdPagedList<MomentsEntity> momentsEntityStdPagedList = momentsMapper.stdPagedEntity(
                new MomentsQuery()
                        .where
                        .selected().eq(req.getSelected(), Objects::nonNull)
                        .end()
                        .orderBy
                        .likeCount().desc().end()
                        .limit(req.limitStartPage(), req.limitEndPage())
        );
        List<MomentsEntity> data = momentsEntityStdPagedList.getData();
        if (CollectionUtil.isEmpty(data)) {
            return HttpReturn.successPageResult();
        }
        List<Long> momentsIdList = ListUtils.emptyIfNull(data).stream()
                .map(MomentsEntity::getId).collect(Collectors.toList());
        List<Long> userIdList = ListUtils.emptyIfNull(data).stream()
                .map(MomentsEntity::getUserId).collect(Collectors.toList());

        List<User> users = userService.listByIds(userIdList);

        Map<Long, User> userMap = ListUtils.emptyIfNull(users).stream()

                .collect(toMap(User::getId, Function.identity(), (oldValue, newValue) -> newValue));

        List<MomentsPicsEntity> momentsPicsEntities = momentsPicsMapper.listEntity(
                new MomentsPicsQuery()
                        .where
                        .momentsId().in(momentsIdList)
                        .end()
        );
        Map<Long, List<MomentsPicsEntity>> momentsPicsMap = ListUtils.emptyIfNull(momentsPicsEntities).stream()
                .collect(Collectors.groupingBy(MomentsPicsEntity::getMomentsId));
        return PageUtil.transferPageHttpReturn(req, momentsEntityStdPagedList, (x) -> {
            MomentsRsp momentsRsp = new MomentsRsp();
            momentsRsp.setMomentsId(x.getId());
            momentsRsp.setContent(x.getContent());

            List<MomentsPicsEntity> momentsPicsEntities1 = momentsPicsMap.get(x.getId());
            if (CollectionUtil.isNotEmpty(momentsPicsEntities1)) {
                momentsRsp.setPics(ListUtils.emptyIfNull(momentsPicsEntities1).stream()
                        .map(MomentsPicsEntity::getPicUrl).collect(Collectors.toList()));
            }
            momentsRsp.setUserId(x.getUserId());
            User user = userMap.get(x.getUserId());
            if (Objects.nonNull(user)) {
                momentsRsp.setNickName(user.getNickname());
            }
            momentsRsp.setSelected(x.getSelected());
            return momentsRsp;
        });
    }

    @Override
    public UnReadCountRsp getUnReadMoments(User user) {
        UnReadCountRsp unReadCountRsp = new UnReadCountRsp();

        final long[] totalUnRead = {0L};
        List<UnReadMomentsReviewRsp> unReadMomentsReviewRsps = Lists.newArrayList();

        // 我发表的动态，未读的评论
        List<MomentsReviewEntity> momentsReviewEntities = momentsReviewMapper.listEntity(
                new MomentsReviewQuery()
                        .where
                        .publishUserId().eq(user.getId())
                        .isRead().isFalse()
                        .end()
        );

        Map<Long, List<MomentsReviewEntity>> momentsReviewEntityMap =
                ListUtils.emptyIfNull(momentsReviewEntities).stream()
                        .collect(Collectors.groupingBy(MomentsReviewEntity::getMomentsId));

        momentsReviewEntityMap.forEach((momentsId, mreList) -> {
            UnReadMomentsReviewRsp unReadMomentsReviewRsp = new UnReadMomentsReviewRsp();
            unReadMomentsReviewRsp.setMomentsId(momentsId);
            totalUnRead[0] = totalUnRead[0] + mreList.size();
            unReadMomentsReviewRsp.setUnReadCount((long) mreList.size());
            unReadMomentsReviewRsp.setReviewNickName(mreList.get(0).getUserNickName());
            unReadMomentsReviewRsp.setContent(mreList.get(0).getContent());
            unReadMomentsReviewRsps.add(unReadMomentsReviewRsp);
        });
        // 我评论别人帖子，未读@我的评论
        List<MomentsReviewEntity> atReviewEntities = momentsReviewMapper.listEntity(
                new MomentsReviewQuery()
                        .where
                        .atUserId().eq(user.getId())
                        .atIsRead().isFalse()
                        .end()
        );
        Map<Long, List<MomentsReviewEntity>> atMomentsReviewEntityMap =
                ListUtils.emptyIfNull(atReviewEntities).stream()
                        .collect(Collectors.groupingBy(MomentsReviewEntity::getMomentsId));
        atMomentsReviewEntityMap.forEach((momentsId, mreList) -> {
            UnReadMomentsReviewRsp unReadMomentsReviewRsp = new UnReadMomentsReviewRsp();
            unReadMomentsReviewRsp.setMomentsId(momentsId);
            totalUnRead[0] = totalUnRead[0] + mreList.size();
            unReadMomentsReviewRsp.setUnReadCount((long) mreList.size());
            unReadMomentsReviewRsp.setReviewNickName(mreList.get(0).getUserNickName());
            unReadMomentsReviewRsp.setContent(mreList.get(0).getContent());
            unReadMomentsReviewRsps.add(unReadMomentsReviewRsp);
        });
        unReadCountRsp.setTotalUnReadCount(totalUnRead[0]);
        unReadCountRsp.setUnReadMomentsReviewRsps(unReadMomentsReviewRsps);
        return unReadCountRsp;
    }

    @Override
    public Long getUnReadMomentsCount(User user) {
        // 我发表的动态，未读的评论
        int count = momentsReviewMapper.count(
                new MomentsReviewQuery()
                        .where
                        .publishUserId().eq(user.getId())
                        .isRead().isFalse()
                        .end()
        );
        // 我评论别人帖子，未读@我的评论
        int count1 = momentsReviewMapper.count(

                new MomentsReviewQuery()
                        .where
                        .atUserId().eq(user.getId())
                        .atIsRead().isFalse()
                        .end()
        );
        return (long) count + count1;
    }
}
